﻿using System;
using System.Collections.Generic;
using Autodesk.Revit.DB;

namespace YJKArchUtils.FamilyInformationUtility
{
	public static class FamilyInformationUtility
	{
		public static bool TryGetDoorOrWindowsOpeningLocation(FamilyInstance input, out List<XYZ> lstWidthPoint, out List<XYZ> lstHeightPoint, bool ifUseLocationPoint = true)
		{
			lstWidthPoint = new List<XYZ>();
			lstHeightPoint = new List<XYZ>();
			double num = 0.0;
			double num2 = 0.0;
			Curve curve;
			XYZ xyz;
			if (!FamilyInformationUtility.TryGetOpeningInformation(input, ifUseLocationPoint, ref num, ref num2, out curve, out xyz))
			{
				return false;
			}
			double length = curve.Length;
			Curve curve2 = curve.Clone();
			curve2.MakeUnbound();
			double parameter = curve2.Project(xyz).Parameter;
			lstHeightPoint.Add(xyz.Add(XYZ.BasisZ.Multiply(num / 2.0)));
			lstHeightPoint.Add(xyz.Add(-XYZ.BasisZ.Multiply(num / 2.0)));
			double num3 = (curve.GetEndParameter(1) - curve.GetEndParameter(0)) * (num2 / 2.0) / length;
			lstWidthPoint.Add(curve2.Evaluate(parameter - num3, false));
			lstWidthPoint.Add(curve2.Evaluate(parameter + num3, false));
			return true;
		}

		public static List<Solid> GetAllSolid(GeometryElement inputValue, Transform useTransform = null)
		{
			List<Solid> list = new List<Solid>();
			if (!(null == inputValue))
			{
				GeometryElement geometryElement = inputValue;
				if (useTransform != null)
				{
					geometryElement = geometryElement.GetTransformed(useTransform);
				}
				foreach (GeometryObject geometryObject in geometryElement)
				{
					if (!(null == geometryObject))
					{
						if (null != geometryObject as Solid && (geometryObject as Solid).Volume > 1E-06)
						{
							list.Add(geometryObject as Solid);
						}
						if (geometryObject is GeometryInstance)
						{
							list.AddRange(FamilyInformationUtility.GetAllSolid((geometryObject as GeometryInstance).GetSymbolGeometry((geometryObject as GeometryInstance).Transform), null));
						}
					}
				}
			}
			return list;
		}

		public static bool TryGetDoorOrWindowsOpeningBoundaryCurves(FamilyInstance input, out List<Curve> lstBoundaryCurves, bool ifUseLocationPoint = true, bool ifMidPointAtDown = false)
		{
			lstBoundaryCurves = new List<Curve>();
			double num = 0.0;
			double num2 = 0.0;
			Curve curve;
			XYZ xyz;
			if (!FamilyInformationUtility.TryGetOpeningInformation(input, ifUseLocationPoint, ref num, ref num2, out curve, out xyz))
			{
				return false;
			}
			double length = curve.Length;
			Curve curve2 = curve.Clone();
			curve2.MakeUnbound();
			double parameter = curve2.Project(xyz).Parameter;
			double num3 = (curve.GetEndParameter(1) - curve.GetEndParameter(0)) * (num2 / 2.0) / length;
			Curve curve3 = curve2;
			curve3.MakeBound(Math.Min(parameter - num3, parameter + num3), Math.Max(parameter - num3, parameter + num3));
			curve3 = curve3.CreateTransformed(Transform.CreateTranslation(XYZ.BasisZ * (xyz.Z - curve3.Evaluate(0.5, true).Z)));
			double num4;
			double num5;
			if (!ifMidPointAtDown)
			{
				num4 = xyz.Add(XYZ.BasisZ.Multiply(num / 2.0)).Z - curve3.Evaluate(0.5, true).Z;
				num5 = xyz.Add(XYZ.BasisZ.Multiply(-num / 2.0)).Z - curve3.Evaluate(0.5, true).Z;
			}
			else
			{
				num4 = xyz.Add(XYZ.BasisZ.Multiply(num)).Z - curve3.Evaluate(0.5, true).Z;
				num5 = 0.0;
			}
			lstBoundaryCurves.Add(curve3.CreateTransformed(Transform.CreateTranslation(XYZ.BasisZ * num4)));
			lstBoundaryCurves.Add(curve3.CreateTransformed(Transform.CreateTranslation(XYZ.BasisZ * num5)));
			lstBoundaryCurves.Add(Line.CreateBound(lstBoundaryCurves[0].GetEndPoint(0), lstBoundaryCurves[1].GetEndPoint(0)));
			lstBoundaryCurves.Add(Line.CreateBound(lstBoundaryCurves[0].GetEndPoint(1), lstBoundaryCurves[1].GetEndPoint(1)));
			return true;
		}

		private static bool TryGetOpeningInformation(FamilyInstance input, bool ifUseLocationPoint, ref double heightValue, ref double widthValue, out Curve hostCurve, out XYZ usePoint)
		{
			hostCurve = null;
			usePoint = null;
			if (input.Category.Id.IntegerValue != -2000023 && input.Category.Id.IntegerValue != -2000014)
			{
				return false;
			}
			if (!ifUseLocationPoint)
			{
				BoundingBoxXYZ boundingBoxXYZ = input.get_BoundingBox(null);
				if (boundingBoxXYZ == null)
				{
					return false;
				}
				usePoint = boundingBoxXYZ.Max.Add(boundingBoxXYZ.Min).Divide(2.0);
			}
			else
			{
				LocationPoint locationPoint = input.Location as LocationPoint;
				if (locationPoint == null)
				{
					return false;
				}
				usePoint = locationPoint.Point;
			}
			if (input.Host == null)
			{
				return false;
			}
			Wall wall = input.Host as Wall;
			if (wall == null)
			{
				return false;
			}
			LocationCurve locationCurve = wall.Location as LocationCurve;
			if (locationCurve == null)
			{
				return false;
			}
			hostCurve = locationCurve.Curve;
			Parameter parameter = input.Symbol.get_Parameter(BuiltInParameter.CASEWORK_WIDTH);
			Parameter parameter2 = input.Symbol.get_Parameter(BuiltInParameter.FAMILY_HEIGHT_PARAM);
			if (parameter == null || parameter2 == null || (int)parameter.StorageType != 2 || (int)parameter2.StorageType != 2)
			{
				return false;
			}
			heightValue = parameter2.AsDouble();
			widthValue = parameter.AsDouble();
			return true;
		}
	}
}
